package com.jiejie.redis;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Controller
public class RedisController {

    @Autowired
    private RedisTemplate redisTemplate;

    /**
     * 未加锁
     * ++操作不是一个原子操作
     * @return
     */
    @GetMapping("/t2")
    public String test02(){
        //1. 查询num值
        Object value = redisTemplate.opsForValue().get("num");
        //2. 判断num是否为空
        if(value==null)
            return "error";
        int num = Integer.parseInt(value+"");
        //将num值+1
        redisTemplate.opsForValue().set("num",++num);
        return "ok";
    }

    /**
     * 提前在redis中设置set num 0
     */
    @GetMapping("/t1")
    public String test01(){
        //1. 获取锁 - setnx
        Boolean flag = redisTemplate.opsForValue().setIfAbsent("lock",1);
        //2. 判断是否获取锁
        System.out.println("flag:"+flag);
        if(flag){
            //1. 查询num值
            Object value = redisTemplate.opsForValue().get("num");
            //2. 判断num是否为空
            if(value==null)
                return "error";
            int num = Integer.parseInt(value+"");
            //将num值+1
            redisTemplate.opsForValue().set("num",++num);
            //3. 释放锁
            redisTemplate.delete("lock");
        }else{
            try {
                //获取锁失败、每隔0.1秒再获取
                Thread.sleep(100);
                test01();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "ok";
    }

    /**
     * 提前在redis中设置set num 0
     * 设置了过期时间
     */
    @GetMapping("/t3")
    public String test03(){
        //1. 获取锁 - setnx
        Boolean flag = redisTemplate.opsForValue().setIfAbsent("lock",1,3, TimeUnit.SECONDS);
        //2. 判断是否获取锁
        System.out.println("flag:"+flag);
        if(flag){
            //1. 查询num值
            Object value = redisTemplate.opsForValue().get("num");
            //2. 判断num是否为空
            if(value==null)
                return "error";
            int num = Integer.parseInt(value+"");
            //将num值+1
            redisTemplate.opsForValue().set("num",++num);
            //3. 释放锁
            redisTemplate.delete("lock");
        }else{
            try {
                //获取锁失败、每隔0.1秒再获取
                Thread.sleep(100);
                test01();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "ok";
    }


    /**
     * 优化之UUID防误删
     * 提前在redis中设置set num 0
     * 设置了过期时间
     */
    @GetMapping("/t4")
    public String test04(){
        String uuid = UUID.randomUUID().toString();
        //1. 获取锁 - setnx
        Boolean flag = redisTemplate.opsForValue().setIfAbsent("lock",uuid,3, TimeUnit.SECONDS);
        //2. 判断是否获取锁
        System.out.println("flag:"+flag);
        if(flag){
            //1. 查询num值
            Object value = redisTemplate.opsForValue().get("num");
            //2. 判断num是否为空
            if(value==null)
                return "error";
            int num = Integer.parseInt(value+"");
            //将num值+1
            redisTemplate.opsForValue().set("num",++num);

            if(uuid.equals((String)redisTemplate.opsForValue().get("lock"))) {
                //3. 释放锁
                redisTemplate.delete("lock");
            }
        }else{
            try {
                //获取锁失败、每隔0.1秒再获取
                Thread.sleep(100);
                test01();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        return "ok";
    }
}
